package com.ssy.lingxi.report.serviceimpl.tally;

import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.constant.member.MemberRoleEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisUtils;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.report.entity.report.MemberTallyReportDO;
import com.ssy.lingxi.report.model.bo.MemberTallyReportBO;
import com.ssy.lingxi.report.model.vo.response.TallyReportVO;
import com.ssy.lingxi.report.repository.report.MemberTallyReportRepository;
import com.ssy.lingxi.report.service.IContractReportService;
import com.ssy.lingxi.report.service.IMemberReportService;
import com.ssy.lingxi.report.service.tally.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TallyReportServiceImpl implements ITallyReportService {

    @Resource
    private MemberTallyReportRepository repository;

    @Resource
    private IRedisUtils redisUtils;

    @Resource
    private IMemberTallyService memberTallyService;

    @Resource
    private IAfterSaleTallyService afterSaleTallyService;

    @Resource
    private ITradeTallyService tradeTallyService;

    @Resource
    private IAccountTallyService accountTallyService;

    @Resource
    private ISettleAccountTallyService settleAccountTallyService;

    @Resource
    private ICommodityTallyService commodityTallyService;

    @Resource
    private ILogisticsTallyService logisticsTallyService;

    @Resource
    private IEnhanceTallyService enhanceTallyService;
    @Resource
    private IContractTallyService contractTallyService;
    @Resource
    private IPurchaseTallyService purchaseTallyService;
    @Resource
    private IOrderTallyService orderTallyService;
    @Resource
    private IContractReportService contractReportService;
    @Resource
    private IMemberReportService memberReportService;

    private static final Logger logger = LoggerFactory.getLogger(TallyReportServiceImpl.class);

    /**
     * 获取计数数据
     * @param user
     * @return
     */
    @Override
    public Wrapper<TallyReportVO> getTallyReport(UserLoginCacheDTO user) {

        TallyReportVO result;
        String key = (Constants.REDIS_KEY_REPORT_TALLY + user.getMemberId() + "_" + user.getMemberRoleId());
        Object reportObj = redisUtils.get(key, Constants.REDIS_REPORT_INDEX);
        if (reportObj == null) {
            // 缓存没查询到数据时，读取数据库数据，并缓存
            MemberTallyReportDO reportDO = repository.findByMemberIdAndRoleId(user.getMemberId(), user.getMemberRoleId());
            if (reportDO == null) {
                // 没有数据时，初始化一条，计数为0
                reportDO = new MemberTallyReportDO();
                reportDO.setMemberId(user.getMemberId());
                reportDO.setRoleId(user.getMemberRoleId());
            }
            // 转换数据
            result = convertData(reportDO);
            redisUtils.set(key, reportDO, Constants.REDIS_REPORT_INDEX);
        } else {
            MemberTallyReportDO reportDO = (MemberTallyReportDO) reportObj;
            // 转换数据
            result = convertData(reportDO);
        }
        return Wrapper.success(result);
    }

    /**
     * 获取计数详情
     * @param user
     * @return
     */
    @Override
    public MemberTallyReportDO getDetail(UserLoginCacheDTO user) {
        return getTally(user.getMemberId(), user.getMemberRoleId());
    }

    /**
     * 根据会员id与角色id查询统计计数
     * @author 伍将
     * @date 2020/12/22
     * @param memberId:
     * @param roleId:
     * @return:
     **/
    @Override
    public MemberTallyReportDO getTallyDetail(Long memberId, Long roleId) {
        return getTally(memberId, roleId);
    }

    /**
     * 获取计数信息
     * @author 伍将
     * @date 2020/12/22
     * @param memberId:
     * @param roleId:
     * @return:
     **/
    private MemberTallyReportDO getTally(Long memberId, Long roleId) {
        String key = (Constants.REDIS_KEY_REPORT_TALLY + memberId + "_" + roleId);
        MemberTallyReportDO reportDO = redisUtils.get(key, Constants.REDIS_REPORT_INDEX, MemberTallyReportDO.class);

        if (reportDO == null) {
            // 缓存没查询到数据时，读取数据库数据，并缓存
            reportDO = repository.findByMemberIdAndRoleId(memberId, roleId);
            if (reportDO == null) {
                // 没有数据时，初始化一条，计数为0
                reportDO = new MemberTallyReportDO();
                reportDO.setMemberId(memberId);
                reportDO.setRoleId(roleId);
            }
            redisUtils.set(key, reportDO, Constants.REDIS_REPORT_INDEX);
        }

        return reportDO;
    }

    /**
     * 更新计数统计
     * 异步处理数据
     * @param noticeVO
     */
    @Override
    public void updateTallyReport(OperateNoticeVO noticeVO) {
        MemberTallyReportDO reportDO = repository.findByMemberIdAndRoleId(noticeVO.getMemberId(), noticeVO.getRoleId());
        if (reportDO == null) {
            // 没有数据时，初始化一条，计数为0
            reportDO = new MemberTallyReportDO();
            reportDO.setMemberId(noticeVO.getMemberId());
            reportDO.setRoleId(noticeVO.getRoleId());
        }

        reportDO = setData(reportDO, noticeVO);
        // 更新缓存
        String key = (Constants.REDIS_KEY_REPORT_TALLY + noticeVO.getMemberId() + "_" + noticeVO.getRoleId());
        redisUtils.set(key, reportDO, Constants.REDIS_REPORT_INDEX);
        //更新db
        repository.save(reportDO);

    }

    /**
     * 转换数据
     * @param reportDO
     * @return
     */
    private TallyReportVO convertData(MemberTallyReportDO reportDO) {

        // 确保转换的数据一定有值返回
        TallyReportVO result = new TallyReportVO();
        if (reportDO == null) {
            reportDO = new MemberTallyReportDO();
        }
        if (reportDO.getTallyReport() == null) {
            reportDO.setTallyReport(new MemberTallyReportBO());
        }

        // 转换售后
        result.setAfterSale(afterSaleTallyService.convertAfterSaleTally(reportDO.getTallyReport()));
        // 转换交易
        result.setTrade(tradeTallyService.convertTradeTally(reportDO.getTallyReport()));
        // 转换资金账户
        result.setAccount(accountTallyService.convertAccount(reportDO.getTallyReport()));
        // 转换结算
        result.setSettleAccount(settleAccountTallyService.convertSettleAccount(reportDO.getTallyReport()));
        // 转换商品
        result.setCommodity(commodityTallyService.convertCommodityTally(reportDO.getTallyReport().getCommodity()));
        // 转换物流
        result.setLogistics(logisticsTallyService.convertLogistics(reportDO.getTallyReport().getLogistics()));
        // 转换加工
        result.setEnhance(enhanceTallyService.convertEnhance(reportDO.getTallyReport()));
        // 转换会员
        result.setMember(memberTallyService.convertMember(reportDO.getTallyReport()));
        /*****************homeStatistics*************/
        // 转换合同
        result.setContract(contractTallyService.convertContractTally(reportDO.getTallyReport()));
        // 转换采购
        if(MemberRoleEnum.PLATFORM.getMemberId().equals(reportDO.getMemberId())){
            result.setPurchase(purchaseTallyService.convertPlatformPurchaseTally(reportDO.getTallyReport().getPlatformPurchase()));
        }else{
            result.setPurchase(purchaseTallyService.convertPurchaseTally(reportDO.getTallyReport()));
        }

        //订单
        result.setOrder(orderTallyService.convertOrderTally(reportDO.getTallyReport()));
        return result;
    }

    /**
     * 设置数据
     * @param reportDO
     * @param noticeVO
     * @return
     */
    private MemberTallyReportDO setData(MemberTallyReportDO reportDO, OperateNoticeVO noticeVO) {
        if (reportDO == null) {
            reportDO = new MemberTallyReportDO();
        }
        MemberTallyReportBO tallyReport = reportDO.getTallyReport();
        if (tallyReport == null) {
            tallyReport = new MemberTallyReportBO();
        }
        if (noticeVO != null) {
            // 设置售后
            tallyReport = afterSaleTallyService.setAfterSaleTally(tallyReport, noticeVO);
            // 设置交易
            tallyReport = tradeTallyService.setTradeTally(tallyReport, noticeVO);
            // 设置资金账户
            tallyReport = accountTallyService.setAccount(tallyReport, noticeVO);
            // 设置结算
            tallyReport = settleAccountTallyService.setSettleAccountTally(tallyReport, noticeVO);
            // 设置商品
            tallyReport = commodityTallyService.setCommodityTally(tallyReport, noticeVO);
            // 设置物流
            tallyReport = logisticsTallyService.setLogisticsTally(tallyReport, noticeVO);
            // 设置加工
            tallyReport = enhanceTallyService.setEnhanceTally(tallyReport, noticeVO);
            // 设置会员
            tallyReport = memberTallyService.setMemberTally(tallyReport, noticeVO);

            //设置合同
            tallyReport = contractTallyService.setContractTally(tallyReport, noticeVO);
            //设置采购
            tallyReport = purchaseTallyService.setPurchaseTally(tallyReport, noticeVO);
            //设置订单
            tallyReport = orderTallyService.setOrderTally(tallyReport, noticeVO);
        }

        reportDO.setTallyReport(tallyReport);

        return reportDO;
    }

    /**
     * 统计计数
     */
    @Override
    public void statisticsTally() {

        // 查询所有的统计数据
        List<MemberTallyReportDO> reportList = repository.findAll();

        // 更新账户中心数据
        logger.info("开始统计资金账户中心");
        reportList = accountTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计资金账户中心");

        // 更新物流中心数据
        logger.info("开始统计物流中心");
        reportList = logisticsTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计物流中心");

        // 更新售后中心数据
        logger.info("开始统计售后中心");
        reportList = afterSaleTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计售后中心");

        // 更新会员中心数据
        logger.info("开始统计会员中心");
        reportList = memberTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计会员中心");

        // 更新商品中心数据
        logger.info("开始统计商品中心");
        reportList = commodityTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计商品中心");

        // 更新结算中心数据
        logger.info("开始统计结算中心");
        reportList = settleAccountTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计结算中心");

        // 更新加工中心数据
        logger.info("开始统计加工中心");
        reportList = enhanceTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计加工中心");

        // 更新交易中心数据
        logger.info("开始统计交易中心");
        reportList = tradeTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        }
        logger.info("结束统计交易中心");

        // 更新合同中心数据
        logger.info("开始统计合同中心");
        reportList = contractTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计合同中心");

        // 更新采购中心数据
        logger.info("开始统计采购中心");
        reportList = purchaseTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计采购中心");
        // 更新订单中心数据
        logger.info("开始统计订单中心");
        reportList = orderTallyService.statisticsTally(reportList);
        if (reportList != null) {
            repository.saveAll(reportList);
        } else {
            reportList = new ArrayList<>();
        }
        logger.info("结束统计订单中心");
        // 更新缓存
        if (reportList.size() > 0) {
            Map<String, Object> keyValueList = new HashMap<>();
            for (MemberTallyReportDO r : reportList) {
                String key = (Constants.REDIS_KEY_REPORT_TALLY + r.getMemberId() + "_" + r.getRoleId());
                keyValueList.put(key, r);
            }
            redisUtils.setBatch(keyValueList, Constants.REDIS_REPORT_INDEX);
        }

    }


}
